////////////////////////////////////////////////////////////////////////////////
//  实现对象的深度克隆 start
////////////////////////////////////////////////////////////////////////////////
//返回传递给他的任意对象的类
const isClass = (o) => {
    if (o === null) return "Null";
    if (o === undefined) return "Undefined";
    // slice(start, end) 方法可提取字符串的某个部分，并以新的字符串返回被提取的部分。
    // 使用 start（包含） 和 end（不包含） 参数来指定字符串提取的部分。
    // start 参数字符串中第一个字符位置为 0, 第二个字符位置为 1, 以此类推，如果是负数表示从尾部截取多少个字符串，slice(-2) 表示提取原数组中的倒数第二个元素到最后一个元素（包含最后一个元素）。
    // end 参数如果为负数，-1 指字符串的最后一个字符的位置，-2 指倒数第二个字符，以此类推。
    return Object.prototype.toString.call(o).slice(8, -1);
};

const isNullAndUndefined = (value) => {
    let result = true;
    if (value != null && value != undefined) {
        result = false;
    }
    return result;
};
const isString = (value) => {
    let result = true;
    if (isNullAndUndefined(value) == false && isClass(value) != "String") {
        result = false;
    }
    return result;
};
const isObject = (value) => {
    let result = true;
    if (isNullAndUndefined(value) == false && isClass(value) != "Object") {
        result = false;
    }
    return result;
};
const isArray = (value) => {
    let result = true;
    if (isNullAndUndefined(value) == false && isClass(value) != "Array") {
        result = false;
    }
    return result;
};
const isNumber = (value) => {
    let result = true;
    if (isNullAndUndefined(value) == false && isClass(value) != "Number") {
        result = false;
    }
    return result;
};
const isBoolean = (value) => {
    let result = true;
    if (isNullAndUndefined(value) == false && isClass(value) != "Boolean") {
        result = false;
    }
    return result;
};
const isRegExp = (value) => {
    let result = true;
    if (isNullAndUndefined(value) == false && isClass(value) != "RegExp") {
        result = false;
    }
    return result;
};
const isDate = (value) => {
    let result = true;
    if (isNullAndUndefined(value) == false && isClass(value) != "Date") {
        result = false;
    }
    return result;
};
const isSymbol = (value) => {
    let result = true;
    if (isNullAndUndefined(value) == false && isClass(value) != "Symbol") {
        result = false;
    }
    return result;
};
const isFunction = (value) => {
    let result = true;
    if (isNullAndUndefined(value) == false && isClass(value) != "Function") {
        result = false;
    }
    return result;
};
////////////////////////////////////////////////////////////////////////////////
//  实现对象的深度克隆 start
////////////////////////////////////////////////////////////////////////////////
//深度克隆
const deepClone = function (obj) {
    let result;
    const oClass = isClass(obj);
    //确定result的类型
    if (oClass === "Object") {
        result = {};
    } else if (oClass === "Array") {
        result = [];
        // }else if (oClass === "Foundation") {
        //   result = new Foundation({});
        // }else if (oClass === "FoundationDetail") {
        //   result = [];
        // }else if (oClass === "FoundationPaiHang") {
        //   result = [];
        // }else if (oClass === "FoundationTongJi") {
        //   result = [];
        // }else if (oClass === "User") {
        //   result = [];
    } else {
        return obj;
    }
    ////////////////////////////////////////
    // 拷贝自身
    ////////////////////////////////////////
    // for...in循环遍历对象自身的和继承的可枚举属性（不含 Symbol 属性）。
    // for (key in obj) {
    // 拷贝自身属性和方法-》 Object.keys返回一个数组，包括对象自身的（不含继承的）所有可枚举属性（不含 Symbol 属性）的键名。
    // for (key of Object.keys(obj)) {

    // Reflect.ownKeys返回一个数组，包含对象自身的（不含继承的）所有键名，不管键名是 Symbol 或字符串，也不管是否可枚举。
    for (const key of Reflect.ownKeys(obj)) {
        const copy = obj[key];
        // if (
        //   isClass(copy) == "Object" ||
        //   isClass(copy) == "Foundation" ||
        //   isClass(copy) == "FoundationDetail" ||
        //   isClass(copy) == "FoundationPaiHang" ||
        //   isClass(copy) == "FoundationTongJi" ||
        //   isClass(copy) == "User"
        // )
        if (isClass(copy) == "Object") {
            // result[key] = arguments.callee(copy); //递归调用
            result[key] = deepClone(copy); //递归调用
        } else if (isClass(copy) == "Array") {
            // result[key] = arguments.callee(copy);
            result[key] = deepClone(copy); //递归调用
        } else {
            // result[key] = copy;
            // console.log("aaaa" + isClass(copy));
            if (isNullAndUndefined(copy)) {
                Reflect.defineProperty(result, key, {
                    value: copy,
                    writable: true,
                    enumerable: true,
                    configurable: true,
                });
            } else {
                Reflect.defineProperty(
                    result,
                    key,
                    Reflect.getOwnPropertyDescriptor(
                        obj,
                        key
                    )
                );
            }
            // Object.getOwnPropertyDescriptor(obj, key);
        }
    }
    ////////////////////////////////////////
    //拷贝原型
    ////////////////////////////////////////
    //拷贝原型的属性和方法-》 Object.keys返回一个数组，包括对象自身的（不含继承的）所有可枚举属性（不含 Symbol 属性）的键名。
    const protoObj = Reflect.getPrototypeOf(obj);
    if (protoObj == Array.prototype) {
        // 防止出现类数组对象
        Reflect.setPrototypeOf(result, Array.prototype);
    } else {
        Reflect.setPrototypeOf(result, {});
    }
    const resultProtoObj = Reflect.getPrototypeOf(result);
    //拷贝原型-》属性和方法
    if (isNullAndUndefined(protoObj) == false) {
        for (const key of Reflect.ownKeys(protoObj)) {
            const copy = protoObj[key] || obj[key];// 防止class中的getter setter 原型无法读取值，所以要从实例属性上取下值
            // if (
            //   isClass(copy) == "Object" ||
            //   isClass(copy) == "Foundation" ||
            //   isClass(copy) == "FoundationDetail" ||
            //   isClass(copy) == "FoundationPaiHang" ||
            //   isClass(copy) == "FoundationTongJi" ||
            //   isClass(copy) == "User"
            if (isClass(copy) == "Object") {
                // resultProtoObj[key] = arguments.callee(copy); //递归调用
                resultProtoObj[key] = deepClone(copy); //递归调用
            } else if (isClass(copy) == "Array") {
                // resultProtoObj[key] = arguments.callee(copy);
                resultProtoObj[key] = deepClone(copy); //递归调用
            } else {
                // resultProtoObj[key] = copy;
                // console.log("bbbb" + isClass(copy));
                if (isNullAndUndefined(copy)) {
                    Reflect.defineProperty(resultProtoObj, key, {
                        value: copy,
                        writable: true,
                        enumerable: true,
                        configurable: true,
                    });
                } else {
                    Reflect.defineProperty(
                        resultProtoObj,
                        key,
                        Reflect.getOwnPropertyDescriptor(
                            protoObj,
                            key
                        )
                    );
                }
            }
        }
    }
    return result;
};
////////////////////////////////////////////////////
//深度遍历 数组和对象 返回value
////////////////////////////////////////////////////
// , { name: "szq", age: 11, [Symbol("sex")]: "man" }
// var arr = [1, [[2, 3], 4], [5, 6], 7, { name: "szq", age: 11, [Symbol("sex")]: "man" }];
// var arr = [1, 2, 3];
// var arr = 1;
const deepSearchvalues = function* deepSearch(obj) {
    var oClass = isClass(obj);
    var keys = [];
    //确定类型
    if (oClass === "Object") {
        // Reflect.ownKeys返回一个数组，包含对象自身的（不含继承的）所有键名，不管键名是 Symbol 或字符串，也不管是否可枚举。
        keys = Reflect.ownKeys(obj);
    } else if (oClass === "Array") {
        // keys()是对数组键名的遍历
        keys = obj.keys();
    } else {
        yield obj;
    }
    if (oClass === "Object" || oClass === "Array") {
        for (let key of keys) {
            let copy = obj[key];
            if (isClass(copy) == "Object" || isClass(copy) === "Array") {
                yield* deepSearch(copy);//递归调用
            } else {
                yield copy;
            }
        }
    }

}
////////////////////////////////////////////////////
//深度遍历对象 返回 [key,value]
////////////////////////////////////////////////////
// , { name: "szq", age: 11, [Symbol("sex")]: "man" }
// var arr = [1, [[2, 3], 4], [5, 6], 7, { name: "szq", age: 11, [Symbol("sex")]: "man" }];
// var arr = [1, 2, 3];
// var arr = 1;
const deepSearchObj = function* deepSearchObj(obj) {
    var oClass = isClass(obj);
    var keys = [];
    //确定类型
    if (oClass === "Object") {
        // Reflect.ownKeys返回一个数组，包含对象自身的（不含继承的）所有键名，不管键名是 Symbol 或字符串，也不管是否可枚举。
        keys = Reflect.ownKeys(obj);
    } else if (oClass === "Array") {
        // keys()是对数组键名的遍历
        keys = obj.keys();
    } else {
        yield [obj, obj];
    }
    if (oClass === "Object" || oClass === "Array") {
        for (let key of keys) {
            let copy = obj[key];
            if (isClass(copy) == "Object" || isClass(copy) === "Array") {
                yield* deepSearchObj(copy);//递归调用
            } else {
                yield [key, obj[key]];;
            }
        }
    }

}
////////////////////////////////////////////////////
//深度遍历对象 返回 {key:value}
////////////////////////////////////////////////////
// , { name: "szq", age: 11, [Symbol("sex")]: "man" }
// var arr = [1, [[2, 3], 4], [5, 6], 7, { name: "szq", age: 11, [Symbol("sex")]: "man" }];
// var arr = [1, 2, 3];
// var arr = 1;
const deepSearchObj2 = function* deepSearchObj2(obj) {
    var oClass = isClass(obj);
    var keys = [];
    //确定类型
    if (oClass === "Object") {
        // Reflect.ownKeys返回一个数组，包含对象自身的（不含继承的）所有键名，不管键名是 Symbol 或字符串，也不管是否可枚举。
        keys = Reflect.ownKeys(obj);
    } else if (oClass === "Array") {
        // keys()是对数组键名的遍历
        keys = obj.keys();
    } else {
        yield { [obj]: obj };
    }
    if (oClass === "Object" || oClass === "Array") {
        for (let key of keys) {
            let copy = obj[key];
            if (isClass(copy) == "Object" || isClass(copy) === "Array") {
                yield* deepSearchObj2(copy);//递归调用
            } else {
                yield { [key]: obj[key] };;
            }
        }
    }

}


class Sleep {
    constructor(timeout) {
        this.timeout = timeout;
        this.mSleepTime = 0;
    }
    then(resolve, reject) {
        const startTime = Date.now();
        let that = this;
        setTimeout(
            () => {
                that.mSleepTime = Date.now() - startTime;
                resolve(that.sleeptime);
            },
            that.timeout
        );
    }
    get sleeptime() { return this.mSleepTime }

}
//  休眠
const threadsleep = async (mtime) => {
    const sleepTime = await new Sleep(mtime);
    return sleepTime;
};
export { deepClone, isClass, deepSearchvalues, deepSearchObj, deepSearchObj2, threadsleep }

// export default { deepClone, isClass, deepSearch }